﻿using Microsoft.Extensions.DependencyInjection;
using SimpleORM.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace SimpleORM.Infrastructure
{
    /// <summary>
    /// 提供用于按特性中的生命周期注入业务组件的扩展方法
    /// 该类为封闭类，需要修改请继承并重写它，不能直接修改
    /// </summary>
    public static class IocInfo
    {
        /// <summary>
        /// 按特性中的生命周期注入业务组件，该方法主要实现接口与实现的IOC注册
        /// 每个接口必须有对应的实现，每个实现必须有接口
        /// </summary>
        /// <param name="service"></param>
        public static void AddBusiness(this IServiceCollection service) //具体方法
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Ioc容器开始注册：\n");

            var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            var referencedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();

            foreach (var assemblyName in referencedAssemblies)
            {
                if (!loadedAssemblies.Any(a => a.GetName().Name == assemblyName.Name))
                {
                    // 加载未被加载的程序集
                    Assembly.Load(assemblyName);
                }
            }
            //var type = typeof(SimpleORM.Service.Service.Getuser);
            //获取有ServiceAttribute特性的所有类
            List <Type> types = AppDomain.CurrentDomain
                .GetAssemblies()
                .SelectMany(x => x.GetTypes())
                .Where(t => t.IsClass && !t.IsAbstract
                        && t.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0
                        )
                .ToList();

            types.ForEach(impl =>
            {
                //获取该类所继承的所有接口
                Type[] interfaces = impl.GetInterfaces();
                //获取该类注入的生命周期
                var lifetime = impl.GetCustomAttribute<ServiceAttribute>().LifeTime;

                interfaces.ToList().ForEach(i =>
                {
                    Console.WriteLine("注册接口：{0}，实现：{1}，项目：{2}，命名空间：{3}" + "\n", i.Name, impl.Name, impl.Assembly.GetName().Name, impl.Namespace);

                    switch (lifetime)
                    {
                        case ServiceLifetime.Singleton:
                            service.AddSingleton(i, impl);
                            break;
                        case ServiceLifetime.Scoped:
                            service.AddScoped(i, impl);
                            break;
                        case ServiceLifetime.Transient:
                            service.AddTransient(i, impl);
                            break;
                    }
                });
            });

            Console.WriteLine("Ioc容器注册完成\n");
        }


    }
}
